package it.avantsoft.ls.gl;

import org.apache.log4j.Logger;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.SecureRandom;
import java.util.Random;

public class AcceptorChild extends Thread {
    private static Logger log = Logger.getLogger(AcceptorChild.class);

    protected ServerSocket serverSocket;
    private GroupLeaderHandler groupLeaderHandler;
    private Random random;

    private boolean stop;

    public AcceptorChild(ServerSocket serverSocket, GroupLeaderHandler groupLeaderHandler) {
        super("AcceptorChild");
        this.serverSocket = serverSocket;
        this.groupLeaderHandler = groupLeaderHandler;
        try {
            random = SecureRandom.getInstance("SHA1PRNG");
        } catch (Exception e) {
            log.error("Could not get secure random for ID generation ", e);
            random = new Random();
        }
        random.setSeed(random.nextLong() ^ hashCode() ^ (this.hashCode() << 31) ^ Runtime.getRuntime().freeMemory());
        stop = false;
        groupLeaderHandler.setSelfInfo(groupLeaderHandler.getHostAddress(), groupLeaderHandler.getListeningPort());
    }

    public long getRandom(long variation) {
        long l = random.nextLong() ^ variation;
        return l < 0 ? -l : l;
    }

    public void shutdown() {
        try {
            serverSocket.close();
            stop = true;
        } catch (IOException e) {

        }
    }

    public void run() {
        while (!stop) {
            try {
                Socket peerSocket = serverSocket.accept();

                long r = getRandom(peerSocket.getInetAddress().getHostAddress().hashCode() ^ peerSocket.getPort());
                //128 bit
                String childId = Long.toString(r, 36);

                GroupChildHandler child = new GroupChildHandler(groupLeaderHandler, peerSocket, childId);
                groupLeaderHandler.addConnectingChild(child);

                child.init();
            } catch (IOException e) {
                log.error("Could not accept connection", e);
            }
        }
    }
}
